/**********头文件**********/ 
#include "../inc/Thread_pool.h"

/**********基础函数**********/
/*
函数名：void thread_exit_handler(void *arg)
描述：线程安全退出执行函数
参数：1.用于接收参数的void型指针
返回值：无
*/
void thread_exit_handler(void *arg)
{
	pthread_mutex_unlock((pthread_mutex_t *)arg);
}

/*
函数名：void *routine(void *arg)
描述：线程执行函数
参数：1.用于接收线程池地址的void型指针
返回值：无
*/
void *thread_routine(void *arg)
{
    thread_pool_struct *pool = (thread_pool_struct*)arg;    //用于获取线程池状态
    thread_pool_task_struct* thread_task = NULL;            //用于获取要执行的任务

printf("创建线程：%ud 文件：%s 函数：%s 行 :%d \n",pool->thread->number, __FILE__, __func__, __LINE__);
    while(1)
    {
        //防止线程中途退出不对互斥锁进行解锁
        pthread_cleanup_push(thread_exit_handler, (void *)&pool->lock);
		pthread_mutex_lock(&pool->lock);

        //无任务且线程池存在
        printf("任务数 = %d\n",pool->waiting_tasks);
        while(pool->waiting_tasks == 0 && !pool->shutdown)
		{
			pthread_cond_wait(&pool->cond, &pool->lock);
		}

        //线程池销毁则线程解开互斥锁并退出
        if(pool->waiting_tasks == 0 && pool->shutdown == true)
		{
			pthread_mutex_unlock(&pool->lock);
			pthread_exit(NULL);
		}

printf("取任务线程：%ld 文件：%s 函数：%s 行 :%d \n",pthread_self(), __FILE__, __func__, __LINE__);
        //取出任务
        thread_task = pool->task_list->next;
        pool->task_list->next = thread_task->next;
        pool->waiting_tasks--;
        pthread_mutex_unlock(&pool->lock);
        pthread_cleanup_pop(0);
        //执行任务时不允许取消
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
        
        (thread_task->task)(thread_task->arg);
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    }
    free(thread_task);
    //return 不会触发清理函数
    pthread_exit(NULL);
}

/*
函数名：bool thread_pool_init(&pool,x)
描述：初始化线程池并创建所需的线程
参数：1.要初始化的线程池的地址
     2.要创建的线程的个数
返回值：1——创建成功
       0——创建失败
*/
bool thread_pool_init(thread_pool_unit_struct* pool, unsigned int  threads_number)
{
    //初始化互斥锁
    if(pthread_mutex_init(&pool->pool.lock,NULL))
        {fprintf(stderr,"互斥锁初始化失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
    //初始化条件变量
    if(pthread_cond_init(&pool->pool.cond,NULL))
        {fprintf(stderr,"条件变量初始化失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
    
    //复位标志
    pool->pool.shutdown = false;
    //任务链表与线程表内存申请
pool->pool.thread = calloc(MAX_ACTIVE_THREADS, sizeof(thread_pool_thread_struct));


    pool->pool.task_list = calloc(1,sizeof(struct task));
	pool->pool.tid_array = calloc(MAX_ACTIVE_THREADS, sizeof(pthread_t));
    pool->pool.thread_status = calloc(MAX_ACTIVE_THREADS, sizeof(bool));
    if(pool->pool.task_list == NULL || pool->pool.tid_array == NULL || pool->pool.thread_status == NULL)
        {fprintf(stderr,"calloc内存申请失败:文件:%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}

if(pool->pool.thread == NULL || pool->pool.tid_array == NULL)
        {fprintf(stderr,"calloc内存申请失败:文件:%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
    
        pool->pool.task_list->next = NULL;
    pool->pool.waiting_tasks = 0;
    pool->pool.active_threads = threads_number;
    //创建线程
    for(uint16_t i = 0;i < threads_number;i++)
    {
        if(pthread_create(&((pool->pool.tid_array)[i]), NULL,thread_routine, (void*)pool))
        {fprintf(stderr,"线程创建失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
pool->idx = i;
if(pthread_create(&((pool->pool.thread)[i].tid), NULL,thread_routine, (void*)pool))
{fprintf(stderr,"线程创建失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
else {pool->pool.thread[i].number = i;pool->pool.thread->thread_status = 0;}

    }


    return true;

}
/*
函数名：bool thread_pool_add_task(&pool,func,(void*)5)
描述：线程池添加任务函数
参数：1.要初始化的线程池的地址
     2.要添加的任务函数地址
返回值：1——创建成功
       0——创建失败
*/
bool thread_pool_add_task(thread_pool_struct* pool,void *(*task)(void *arg),void* arg)
{
    //接收任务
    thread_pool_task_struct* task_new = malloc(sizeof(thread_pool_task_struct));
    if(task_new == NULL)
    {
        fprintf(stderr, "allocate memory error\n");
        return false;
    }
    task_new->task = task;
    task_new->arg = arg;

    //查看任务是否满了,操作线程池时需要上锁
    pthread_mutex_lock(&pool->lock);
    if((pool->waiting_tasks) >= MAX_TASK_NUMBER)
    {
        pthread_mutex_unlock(&pool->lock);
		fprintf(stderr, "too many tasks.\n");
		free(task_new);

		return false;
    }

    //遍历任务链表
    thread_pool_task_struct* node_now = pool->task_list;  

    while(node_now->next != NULL)
        node_now = node_now->next;

    node_now->next = task_new;
    task_new->next = NULL;
    
    pool->waiting_tasks++;
    pthread_mutex_unlock(&pool->lock);

    //添加任务后发出信号
    pthread_cond_signal(&pool->cond);
    return true;
}
/*
函数名：bool thread_pool_add_thread(&pool,0)
描述：线程池添加任务函数
参数：1.要初始化的线程池的地址
     2.要添加的任务函数地址
返回值：1——创建成功
       0——创建失败
*/
bool thread_pool_add_thread(thread_pool_struct* pool,unsigned int thread_num)
{
    //访问线程池要上锁
    pthread_mutex_lock(&pool->lock);
    unsigned int num_now = pool->active_threads;
    //判断是否超出最大线程数量
    if(thread_num + pool->active_threads >= MAX_ACTIVE_THREADS)
    {fprintf(stderr,"线程添加失败：文件：%s 函数：%s 行 :%d 原因：%s\n",__FILE__,__func__,__LINE__,"thread space insufficient");return false;}

    //创建线程
    for(uint16_t i = num_now;i < num_now + thread_num;i++)
    {
        if(pthread_create(&((pool->tid_array)[i]), NULL,thread_routine, (void*)pool))
        {fprintf(stderr,"线程创建失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
        pool->active_threads++;
    }
    pthread_mutex_unlock(&pool->lock);
    return true;
}
/*
函数名：int thread_pool_remove_thread(&pool,0)
描述：线程销毁函数
参数：1.要初始化的线程池的地址
     2.要添加的任务函数地址
返回值：成功——剩余的线程数
       失败——返回-1
*/
int thread_pool_remove_thread(thread_pool_struct* pool,unsigned int rm_num)
{
    //操作线程池之前先上锁
    if(pthread_mutex_lock(&pool->lock))
    {fprintf(stderr,"锁资源获取失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}
    //移除数为0直接退出
    if(rm_num == 0)return pool->active_threads;
    

    //解锁
    if(pthread_mutex_unlock(&pool->lock))
    {fprintf(stderr,"解锁失败：文件：%s 函数：%s 行 :%d 原因：%s",__FILE__,__func__,__LINE__,strerror(errno));return false;}

    return pool->active_threads;
}







void *func(void* arg)
{
    printf("这是新任务%d\n",1);
    sleep(1);
}
void *func1(void* arg)
{
    printf("这是新任务%d\n",2);
    sleep(1);
}
//试验区





int main(void)
{

    thread_pool_unit_struct pool;
    thread_pool_init(&pool,1);
    // if(thread_pool_add_task(&pool,func,(void*)5) == false)perror("add task error");
    // //sleep(2);
    // if(thread_pool_add_task(&pool,func1,(void*)5) == false)perror("add task error");
    // printf("这里是主函数\n");
    // thread_pool_add_thread(&pool,0);
    // printf("当前线程数 = %d\n",pool.active_threads);
    while(1);


    return 0;
}

